#!/usr/bin/env python3
# Copyright (c) 2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test asmap config argument for ASN-based IP bucketing.

Verify node behaviour and debug log when launching syscoind in these cases:

1. `syscoind` with no -asmap arg, using /16 prefix for IP bucketing

2. `syscoind -asmap=<absolute path>`, using the unit test skeleton asmap

3. `syscoind -asmap=<relative path>`, using the unit test skeleton asmap

4. `syscoind -asmap/-asmap=` with no file specified, using the default asmap

5. `syscoind -asmap` with no file specified and a missing default asmap file

The tests are order-independent. The slowest test (missing default asmap file)
is placed last.

"""
import os
import shutil

from test_framework.test_framework import SyscoinTestFramework

DEFAULT_ASMAP_FILENAME = 'ip_asn.map' # defined in src/init.cpp
ASMAP = '../../src/test/data/asmap.raw' # path to unit test skeleton asmap
VERSION = 'fec61fa21a9f46f3b17bdcd660d7f4cd90b966aad3aec593c99b35f0aca15853'

def expected_messages(filename):
    return ['Opened asmap file "{}" (59 bytes) from disk.'.format(filename),
            'Using asmap version {} for IP bucketing.'.format(VERSION)]

class AsmapTest(SyscoinTestFramework):
    def set_test_params(self):
        self.setup_clean_chain = False
        self.num_nodes = 1

    def test_without_asmap_arg(self):
        self.log.info('Test syscoind with no -asmap arg passed')
        self.stop_node(0)
        with self.node.assert_debug_log(['Using /16 prefix for IP bucketing']):
            self.start_node(0)

    def test_asmap_with_absolute_path(self):
        self.log.info('Test syscoind -asmap=<absolute path>')
        self.stop_node(0)
        filename = os.path.join(self.datadir, 'my-map-file.map')
        shutil.copyfile(self.asmap_raw, filename)
        with self.node.assert_debug_log(expected_messages(filename)):
            self.start_node(0, ['-asmap={}'.format(filename)])
        os.remove(filename)

    def test_asmap_with_relative_path(self):
        self.log.info('Test syscoind -asmap=<relative path>')
        self.stop_node(0)
        name = 'ASN_map'
        filename = os.path.join(self.datadir, name)
        shutil.copyfile(self.asmap_raw, filename)
        with self.node.assert_debug_log(expected_messages(filename)):
            self.start_node(0, ['-asmap={}'.format(name)])
        os.remove(filename)

    def test_default_asmap(self):
        shutil.copyfile(self.asmap_raw, self.default_asmap)
        for arg in ['-asmap', '-asmap=']:
            self.log.info('Test syscoind {} (using default map file)'.format(arg))
            self.stop_node(0)
            with self.node.assert_debug_log(expected_messages(self.default_asmap)):
                self.start_node(0, [arg])
        os.remove(self.default_asmap)

    def test_default_asmap_with_missing_file(self):
        self.log.info('Test syscoind -asmap with missing default map file')
        self.stop_node(0)
        msg = "Error: Could not find asmap file '\"{}\"'".format(self.default_asmap)
        self.node.assert_start_raises_init_error(extra_args=['-asmap'], expected_msg=msg)

    def run_test(self):
        self.node = self.nodes[0]
        self.datadir = os.path.join(self.node.datadir, self.chain)
        self.default_asmap = os.path.join(self.datadir, DEFAULT_ASMAP_FILENAME)
        self.asmap_raw = os.path.join(os.path.dirname(os.path.realpath(__file__)), ASMAP)

        self.test_without_asmap_arg()
        self.test_asmap_with_absolute_path()
        self.test_asmap_with_relative_path()
        self.test_default_asmap()
        self.test_default_asmap_with_missing_file()


if __name__ == '__main__':
    AsmapTest().main()

@@ -711,16 +711,84 @@
 p file%0A%0A
+6. %60bitcoind -asmap%60 with an empty (unparsable) default asmap file%0A%0A
 The test
@@ -828,16 +828,17 @@
 est test
+s
  (missin
@@ -857,16 +857,28 @@
 map 
-file)%0Ais
+and%0Aempty asmap) are
  pla
@@ -3331,16 +3331,444 @@
 g=msg)%0A%0A
+    def test_empty_asmap(self):%0A        self.log.info('Test bitcoind -asmap with empty map file')%0A        self.stop_node(0)%0A        with open(self.default_asmap, %22w%22, encoding=%22utf-8%22) as f:%0A            f.write(%22%22)%0A        msg = %22Error: Could not parse asmap file %5C%22%7B%7D%5C%22%22.format(self.default_asmap)%0A        self.node.assert_start_raises_init_error(extra_args=%5B'-asmap'%5D, expected_msg=msg)%0A        os.remove(self.default_asmap)%0A%0A
     def 
@@ -4269,16 +4269,48 @@
 _file()%0A
+        self.test_empty_asmap()%0A
 %0A%0Aif __n

add functional test for an empty, unparsable asmap