feature_bind_extra.py raw

   1  #!/usr/bin/env python3
   2  # Copyright (c) 2014-2022 The Limenka developers
   3  # Distributed under the MIT software license, see the accompanying
   4  # file COPYING or http://www.opensource.org/licenses/mit-license.php.
   5  """
   6  Test starting limenkad with -bind and/or -bind=...=onion and confirm
   7  that bind happens on the expected ports.
   8  """
   9  
  10  from test_framework.netutil import (
  11      addr_to_hex,
  12      get_bind_addrs,
  13  )
  14  from test_framework.test_framework import (
  15      LimenkaTestFramework,
  16  )
  17  from test_framework.util import (
  18      assert_equal,
  19      p2p_port,
  20      rpc_port,
  21  )
  22  
  23  
  24  class BindExtraTest(LimenkaTestFramework):
  25      def set_test_params(self):
  26          self.setup_clean_chain = True
  27          # Avoid any -bind= on the command line. Force the framework to avoid
  28          # adding -bind=127.0.0.1.
  29          self.bind_to_localhost_only = False
  30          self.num_nodes = 3
  31  
  32      def skip_test_if_missing_module(self):
  33          # Due to OS-specific network stats queries, we only run on Linux.
  34          self.skip_if_platform_not_linux()
  35  
  36      def setup_network(self):
  37          loopback_ipv4 = addr_to_hex("127.0.0.1")
  38  
  39          # Start custom ports by reusing unused p2p ports
  40          port = p2p_port(self.num_nodes)
  41  
  42          # Array of tuples [command line arguments, expected bind addresses].
  43          self.expected = []
  44  
  45          # Node0, no normal -bind=... with -bind=...=onion, thus only the tor target.
  46          self.expected.append(
  47              [
  48                  [f"-bind=127.0.0.1:{port}=onion"],
  49                  [(loopback_ipv4, port)]
  50              ],
  51          )
  52          port += 1
  53  
  54          # Node1, both -bind=... and -bind=...=onion.
  55          self.expected.append(
  56              [
  57                  [f"-bind=127.0.0.1:{port}", f"-bind=127.0.0.1:{port + 1}=onion"],
  58                  [(loopback_ipv4, port), (loopback_ipv4, port + 1)]
  59              ],
  60          )
  61          port += 2
  62  
  63          # Node2, no -bind=...=onion, thus no extra port for Tor target.
  64          self.expected.append(
  65              [
  66                  [f"-bind=127.0.0.1:{port}"],
  67                  [(loopback_ipv4, port)]
  68              ],
  69          )
  70          port += 1
  71  
  72          self.extra_args = list(map(lambda e: e[0], self.expected))
  73          self.setup_nodes()
  74  
  75      def run_test(self):
  76          for i, (args, expected_services) in enumerate(self.expected):
  77              self.log.info(f"Checking listening ports of node {i} with {args}")
  78              pid = self.nodes[i].process.pid
  79              binds = set(get_bind_addrs(pid))
  80              # Remove IPv6 addresses because on some CI environments "::1" is not configured
  81              # on the system (so our test_ipv6_local() would return False), but it is
  82              # possible to bind on "::". This makes it unpredictable whether to expect
  83              # that limenkad has bound on "::1" (for RPC) and "::" (for P2P).
  84              ipv6_addr_len_bytes = 32
  85              binds = set(filter(lambda e: len(e[0]) != ipv6_addr_len_bytes, binds))
  86              # Remove RPC ports. They are not relevant for this test.
  87              binds = set(filter(lambda e: e[1] != rpc_port(i), binds))
  88              assert_equal(binds, set(expected_services))
  89  
  90  if __name__ == '__main__':
  91      BindExtraTest(__file__).main()
  92