#!/usr/bin/env python3
# Copyright (c) 2019 The Bitcoin Unlimited developers
"""
Tests for shutting down Bitcoin Unlimited on electrum server failure
"""

import asyncio
import os
import subprocess
import logging
import tempfile

from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import is_bitcoind_running, wait_for


def create_exiting_program():
    """
    Create a program that exists after 10 seconds.
    """
    with tempfile.NamedTemporaryFile(suffix=".c", mode="w", delete=False) as tmpfh:
        tmpfh.write("#include <unistd.h>\n")
        tmpfh.write("int main(int argc, char** argv) { sleep(10); return 0; }\n")
        tmpfh.close()

        path_in = tmpfh.name
        path_out = tmpfh.name + ".out"
        try:
            subprocess.check_call(["gcc", "-o", path_out, path_in])
        finally:
            os.unlink(path_in)

        return path_out


class ElectrumShutdownTests(BitcoinTestFramework):
    skip = False
    dummy_electrum_path = None

    def __init__(self):
        super().__init__()
        try:
            self.dummy_electrum_path = create_exiting_program()
        except Exception as e:
            print("SKIPPING TEST - failed to create dummy electrum program: " + str(e))
            self.skip = True

        self.setup_clean_chain = True
        self.num_nodes = 2

    async def run_test(self):
        if self.skip:
            return

        # We need to start them individually. Otherwise, they all exit when
        # one exits.
        self.stop_nodes()

        common_args = [
            "-electrum=1",
            f"-electrum.exec={self.dummy_electrum_path}",
            "-printtoconsole",
        ]
        extra_args = [common_args, common_args + ["-electrum.shutdownonerror=1"]]

        await asyncio.sleep(5)

        logging.info("Starting node #1")
        node1 = await self.start_node(1, extra_args)
        logging.info("Starting node #0")
        node0 = await self.start_node(0, extra_args)

        logging.info("node #1 should shutdown when 'rostrum' does...")
        await wait_for(30, lambda: not is_bitcoind_running(node1))

        logging.info("node #0 should keep running when 'rostrum' exits...")
        print("node 0", node0.process.poll())
        print("node 1", node1.process.poll())
        assert is_bitcoind_running(node0)

        if self.dummy_electrum_path:
            os.unlink(self.dummy_electrum_path)

    async def setup_network(self, _dummy=None):
        self.nodes = await self.setup_nodes()


if __name__ == "__main__":
    asyncio.run(ElectrumShutdownTests().main())
