test: add functional test for anchors.dat #21338

pull brunoerg wants to merge 1 commits into bitcoin:master from brunoerg:2021-03-anchors-test changing 2 files +86 −0
  1. brunoerg commented at 2:01 PM on March 2, 2021: member

    This PR adds a functional test for anchors.dat.

    It creates a node and adds 2 outbound block-relay-only connections and 5 inbound connections. When the node is down, anchors.dat should contain the 2 addresses from the outbound block-relay-only connections.

  2. michaelfolkson commented at 2:10 PM on March 2, 2021: contributor

    Concept ACK

    I was thinking this should be a p2p_ test rather than a feature_ test but maybe you're right...

  3. brunoerg commented at 2:54 PM on March 2, 2021: member

    I added feature_anchors.py in BASE_SCRIPTS

  4. jaonoctus commented at 2:54 PM on March 2, 2021: none

    CI Tests are failing for two reasons so far:

    1. The following scripts are not being run: ['feature_anchors.py']. Check the test lists in test_runner.py
    2. Some lint errors
    feature_anchors.py:31:1: W293 blank line contains whitespace
    feature_anchors.py:77:25: W292 no newline at end of file
    
  5. brunoerg commented at 2:57 PM on March 2, 2021: member

    Thanks, @jaonoctus. Fixed!

  6. jaonoctus approved
  7. jaonoctus commented at 3:04 PM on March 2, 2021: none

    Concept ACK

  8. in test/functional/feature_anchors.py:61 in 13762cda77 outdated
      56 | +        self.log.info("Check anchors.dat file in the node directory")
      57 | +        assert os.path.exists(os.path.join(self.nodes[0].datadir + '/regtest', 'anchors.dat'))
      58 | +
      59 | +        # It should contains only the block-relay-only addresses
      60 | +        self.log.info("Check the addresses in anchors.dat")
      61 | +        for line in open(os.path.join(self.nodes[0].datadir + '/regtest', 'anchors.dat'), 'rb'):
    


    jaonoctus commented at 3:14 PM on March 2, 2021:
            for line in open(os.path.join(self.nodes[0].datadir + '/regtest', 'anchors.dat'), 'rb', encoding='utf8'):
    

    brunoerg commented at 3:48 PM on March 2, 2021:

    I think it won't work because it's binary mode.


    hebasto commented at 3:55 PM on March 2, 2021:

    Anyway, all of the linters must pass.


    jaonoctus commented at 5:20 PM on March 2, 2021:

    Tested ACK. I'm pretty sure It's a false-flag.

    • OS: Ubuntu 20.10

    Without encoding - passes

    Screenshot from 2021-03-02 14-07-31

    With encoding - fail

    Screenshot from 2021-03-02 14-15-21


    I also have checked other tests that are reading binaries. Such as p2p_message_capture.py (line 37) or rpc_dumptxoutset.py (line 40). None have the encoding parameter, which makes sense.

  9. jaonoctus changes_requested
  10. jaonoctus commented at 3:14 PM on March 2, 2021: none

    Python's open(...) seems to be used to open text files without explicitly specifying encoding='utf8'

  11. hebasto commented at 3:55 PM on March 2, 2021: member

    Concept ACK.

  12. DrahtBot added the label Tests on Mar 2, 2021
  13. brunoerg force-pushed on Mar 2, 2021
  14. in test/functional/feature_anchors.py:57 in b1a5e04be4 outdated
      52 | +
      53 | +        self.log.info("Stop node 0")
      54 | +        self.stop_node(0)
      55 | +
      56 | +        self.log.info("Check anchors.dat file in the node directory")
      57 | +        assert os.path.exists(os.path.join(self.nodes[0].datadir + '/regtest', 'anchors.dat'))
    


    MarcoFalke commented at 6:59 PM on March 2, 2021:

    could make the path a named variable to avoid repeating the join three times?


    brunoerg commented at 7:26 PM on March 2, 2021:

    Yeah, no problem! thanks!


    brunoerg commented at 7:35 PM on March 2, 2021:

    Done!

  15. brunoerg force-pushed on Mar 2, 2021
  16. leonardojobim commented at 8:07 PM on March 2, 2021: none

    Approach ACK.

    Tested https://github.com/bitcoin/bitcoin/pull/21338/commits/53046529155a7dd9875604059a7134221d176522 on Ubuntu 20.04. The test has failed intermittently when run several times. The reason is the file anchors.dat sometimes has 2 lines, as shown below. A simple solution for this would be concatenate all line before the validations.

    2021-03-02T19:52:13.969000Z TestFramework (INFO): Check the addresses in anchors.dat
    item (first line): fabfb5da02fc5a030000e1f505000000000000000000000000000000000000ffff7f0000012b6efc5a030000e1f505000000000000000000000000000000000000ffff7f0000012b6d1c665ef1c1d383c4869170e021306a945bdbfb9f39c12bb2e0
    ip_port: 7f0000012b6e
    ip_port in item: True
    ip_port: 7f0000012b6d
    ip_port in item: True
    item (second line): 279f548ecaf3
    ip_port: 7f0000012b6e
    ip_port in item: False
    2021-03-02T19:52:13.969000Z TestFramework (ERROR): Assertion failed
    
  17. brunoerg commented at 9:00 PM on March 2, 2021: member

    @leonardojobim Amazing review! I'm working on it at this moment! Thank you!

  18. brunoerg force-pushed on Mar 2, 2021
  19. brunoerg commented at 9:04 PM on March 2, 2021: member

    @leonardojobim fixed! could you please test it again?

  20. DrahtBot commented at 9:31 PM on March 2, 2021: member

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #19521 (Coinstats Index by fjahr)
    • #18795 (Test: wallet issue with orphaned rewards by domob1812)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  21. leonardojobim approved
  22. leonardojobim commented at 9:54 PM on March 2, 2021: none
  23. jaonoctus approved
  24. in test/functional/feature_anchors.py:11 in a83908f9f7 outdated
       6 | +
       7 | +from test_framework.p2p import P2PInterface
       8 | +from test_framework.test_framework import BitcoinTestFramework
       9 | +from test_framework.util import assert_equal
      10 | +
      11 | +import os
    


    jonatack commented at 12:40 PM on March 6, 2021:

    nit, per PEP8 and test/functional/README.md, this import should be before the framework ones (separated by a blank line)


    jonatack commented at 12:54 PM on March 6, 2021:

    https://www.python.org/dev/peps/pep-0008/#imports

    Imports should be grouped in the following order:

    • Standard library imports.
    • Related third party imports.
    • Local application/library specific imports.

    You should put a blank line between each group of imports.


    brunoerg commented at 1:24 PM on March 6, 2021:

    Thanks, just fixed!

  25. in test/functional/feature_anchors.py:29 in a83908f9f7 outdated
      24 | +        self.setup_nodes()
      25 | +
      26 | +    def run_test(self):
      27 | +        self.log.info("Add 2 block-relay-only connections to node 0")
      28 | +        for i in range(2):
      29 | +            self.log.info(f"block-relay-only: {i}")
    


    jonatack commented at 12:41 PM on March 6, 2021:
                self.log.debug(f"block-relay-only: {i}")
    

    brunoerg commented at 1:35 PM on March 6, 2021:

    Just changed it, it's better debug instead of info for this case.

  26. in test/functional/feature_anchors.py:34 in a83908f9f7 outdated
      29 | +            self.log.info(f"block-relay-only: {i}")
      30 | +            self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i, connection_type="block-relay-only")
      31 | +
      32 | +        self.log.info("Add 5 inbound connections to node 0")
      33 | +        for i in range(5):
      34 | +            self.log.info(f"inbound: {i}")
    


    jonatack commented at 12:41 PM on March 6, 2021:
                self.debug.info(f"inbound: {i}")
    

    brunoerg commented at 1:42 PM on March 6, 2021:

    Just changed it, but the right format is self.log.debug as you suggested above I guess.

  27. in test/functional/feature_anchors.py:61 in a83908f9f7 outdated
      56 | +        node0_anchors_path = os.path.join(self.nodes[0].datadir + '/regtest', 'anchors.dat')
      57 | +
      58 | +        self.log.info("Check anchors.dat file in the node directory")
      59 | +        assert os.path.exists(node0_anchors_path)
      60 | +
      61 | +        # It should contains only the block-relay-only addresses
    


    jonatack commented at 12:47 PM on March 6, 2021:
            # It should contain only the block-relay-only addresses
    
  28. jonatack commented at 12:51 PM on March 6, 2021: member

    Concept ACK and some very light review, will review a bit more soon.

    The file permission of the new test file should be 755 instead of 644.

    -rwxr-xr-x 1 1685 Jan 21 20:54 test/functional/feature_abortnode.py*
    -rw-r--r-- 1 2902 Mar  6 13:37 test/functional/feature_anchors.py
    -rwxr-xr-x 1 4242 Mar  6 13:10 test/functional/feature_asmap.py*
    

    In order to run the test, I had to first run:

    sudo chmod 755 test/functional/feature_anchors.py
    

    Nit: in terms of logging and function naming, I prefer "Test" to "Check that/if"

    Don't hesitate to try running Python linters on your functional test changes like pycodestyle and black to see their suggestions.

  29. brunoerg force-pushed on Mar 6, 2021
  30. brunoerg commented at 1:43 PM on March 6, 2021: member

    Thanks for the review @jonatack. Just pushed some fixes!

  31. in test/functional/feature_anchors.py:60 in 9ef15a0af2 outdated
      55 | +
      56 | +        self.log.info("Stop node 0")
      57 | +        self.stop_node(0)
      58 | +
      59 | +        node0_anchors_path = os.path.join(
      60 | +            self.nodes[0].datadir + "/regtest", "anchors.dat"
    


    aarmoa commented at 10:29 PM on March 7, 2021:

    Hello Bruno. I think we should concatenate regtest sub directory using the os.path.join() function instead of using + "/regtest" (just to avoid assuming the test is running in a Unix based OS). node0_anchors_path = os.path.join( self.nodes[0].datadir, "regtest", "anchors.dat" )


    jonatack commented at 11:30 PM on March 7, 2021:

    Good point.

    In general, don't hesitate to refer to test/functional/feature_asmap.py for an example of a similar kind of test file.

        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)
    

    brunoerg commented at 12:02 AM on March 8, 2021:

    Hello, Abel.. Thanks a lot for the review! Just changed it.

  32. aarmoa changes_requested
  33. brunoerg force-pushed on Mar 7, 2021
  34. aarmoa approved
  35. aarmoa commented at 2:24 AM on March 8, 2021: none

    Approach ACK.

    Tested 0605a3c on Linux Mint 20.

    I tried breaking the test without successing with the following:

    • line 29: change range(2) for range(1) Assertion in check_node_connections(node=self.nodes[0], num_in=5, num_out=2) fails (AssertionError: not(1 == 2))
    • line 36: change range(5) for range(6) Assertion in check_node_connections(node=self.nodes[0], num_in=5, num_out=2) fails as expected (AssertionError: not(6 == 5))
    • Added a line to change expected ip address (ip = "7f000002") before line 73 Assertion that block_relay_nodes_port are included in anchors fail as expected
    • Added a line to change expected ip address (ip = "7f000002") before line 76 Assertion that inbound_nodes_port are not included in anchors still passes as expected
    • Commented out line 81 (self.start_node(0)) Assertion that anchors file does not exist fails as expected.

    Executing the new test alone from command line works correctly (test/functional/feature_anchors.py).

    Executing all functional tests with test/functional/test_runner.py includes new test:

    187/202 - feature_anchors.py passed, Duration: 4 s

    TEST | STATUS | DURATION

    example_test.py | ✓ Passed | 11 s feature_abortnode.py | ✓ Passed | 34 s feature_anchors.py | ✓ Passed | 4 s . . .

  36. simsbluebox approved
  37. simsbluebox commented at 5:43 AM on March 10, 2021: none

    ACK https://github.com/bitcoin/bitcoin/pull/21338/commits/0605a3cbf8ddec39dfbe5c490a872158dc8a6faa, I ran tests OK on Debian 10.8 (buster) and reviewed the code and it looks fine for me.

  38. in test/functional/feature_anchors.py:67 in 0605a3cbf8 outdated
      64 | +        assert os.path.exists(node0_anchors_path)
      65 | +
      66 | +        # It should contain only the block-relay-only addresses
      67 | +        self.log.info("Check the addresses in anchors.dat")
      68 | +
      69 | +        anchors = ""
    


    MarcoFalke commented at 2:45 PM on March 15, 2021:

    wouldn't it make more sense for this to be an array?


    brunoerg commented at 9:32 PM on March 16, 2021:

    I don't think so. I am concatenating the lines to verify if the addresses are into this. I don't think an array would be useful here.


    MarcoFalke commented at 7:27 AM on March 17, 2021:

    Let's assume ip_port is aa and anchors is ['fa', 'af']

    With array:

    >>> 'aa' in ['fa', 'af']
    False
    

    With string

    >>> 'aa' in 'faaf'
    True
    

    Am I missing something?


    brunoerg commented at 12:02 AM on March 18, 2021:

    I'm using string for the reason you're showing with your example. I think the question about using array or string is: how is anchors.dat structured?

    Let's suppose:

    ip_port is 7f0000013e01 and the file content is: fabfb5da02fc5a030000e1f505000000000000000000000000000000000000ffff7f0000013e01fc5a030000e1f505000000000000000000000000000000000000ffff7f0000013e0075f7d7cf33e71e42f8add50c305f091fb881b6fa5633932559d86cd9f6141260

    but we have: fabfb5da02fc5a030000e1f505000000000000000000000000000000000000ffff7f00 (breaks line) 00013e01fc5a030000e1f505000000000000000000000000000000000000ffff7f000 (breaks line) 0013e0075f7d7cf33e71e42f8add50c305f091fb881b6fa5633932559d86cd9f6141260 (breaks line)

    in this case, my logic using string would be useful. But how is the file structure for this case?

    Anyway, almost 100% of my tests showed me that anchors.dat usually has just one line.


    MarcoFalke commented at 7:03 AM on March 18, 2021:

    anchors.dat is binary data, so why would newlines matter and what is the point of rstrip?


    brunoerg commented at 12:34 AM on March 19, 2021:

    I can remove rstrip I guess, it doesn't affect anything, thanks.


    brunoerg commented at 12:43 AM on March 19, 2021:

    So, can I read only the first line? I was using array but the test `was failing, assuming:

    item (first line): fabfb5da02fc5a030000e1f505000000000000000000000000000000000000ffff7f0000012b6efc5a030000e1f505000000000000000000000000000000000000ffff7f0000012b6d1c665ef1c1d383c4869170e021306a945bdbfb9f39c12bb2e0
    ip_port: 7f0000012b6e
    ip_port in item: True
    ip_port: 7f0000012b6d
    ip_port in item: True
    item (second line): 279f548ecaf3
    ip_port: 7f0000012b6e
    ip_port in item: False`
    

    MarcoFalke commented at 6:40 AM on March 19, 2021:

    If newlines don't have a meaning, they shouldn't be interpreted. You can just use read()?


    brunoerg commented at 11:33 PM on March 19, 2021:

    Yes, just pushed the changes. It makes sense. Could you please check?

  39. in test/functional/feature_anchors.py:64 in 0605a3cbf8 outdated
      59 | +        node0_anchors_path = os.path.join(
      60 | +            self.nodes[0].datadir, "regtest", "anchors.dat"
      61 | +        )
      62 | +
      63 | +        self.log.info("Check anchors.dat file in the node directory")
      64 | +        assert os.path.exists(node0_anchors_path)
    


    MarcoFalke commented at 2:46 PM on March 15, 2021:

    I think this check can be skipped (will be checked by open already)


    brunoerg commented at 9:34 PM on March 16, 2021:

    Make sense. When the file doesn't exit in the node directory the open function will return a FileNotFoundError. Thanks!


    brunoerg commented at 9:56 PM on March 16, 2021:

    Done!

  40. MarcoFalke approved
  41. MarcoFalke commented at 2:46 PM on March 15, 2021: member

    Seems fine. Left two comments

  42. brunoerg force-pushed on Mar 16, 2021
  43. brunoerg force-pushed on Mar 16, 2021
  44. brunoerg force-pushed on Mar 19, 2021
  45. test: add functional test for anchors.dat 581791c620
  46. brunoerg force-pushed on Mar 19, 2021
  47. ottosch commented at 1:16 AM on March 20, 2021: none

    Tested ACK. I ran it 100x and they all passed. OS: Archlinux.

    tack-21338

  48. MarcoFalke commented at 7:36 AM on March 20, 2021: member

    Concept ACK 581791c62067403fbeb4e1fd88c1d80549627c94

  49. MarcoFalke requested review from hebasto on Mar 20, 2021
  50. in test/functional/feature_anchors.py:14 in 581791c620
       9 | +from test_framework.p2p import P2PInterface
      10 | +from test_framework.test_framework import BitcoinTestFramework
      11 | +from test_framework.util import assert_equal
      12 | +
      13 | +
      14 | +def check_node_connections(*, node, num_in, num_out):
    


    hebasto commented at 3:34 AM on March 22, 2021:

    This code is used once only. What are benefits of the separated function here?

  51. in test/functional/feature_anchors.py:5 in 581791c620
       0 | @@ -0,0 +1,85 @@
       1 | +#!/usr/bin/env python3
       2 | +# Copyright (c) 2020 The Bitcoin Core developers
       3 | +# Distributed under the MIT software license, see the accompanying
       4 | +# file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5 | +"""Test Anchors functionality"""
    


    hebasto commented at 3:35 AM on March 22, 2021:

    nit:

    """Test block-relay-only anchors functionality"""
    
  52. in test/functional/feature_anchors.py:28 in 581791c620
      23 | +
      24 | +    def setup_network(self):
      25 | +        self.setup_nodes()
      26 | +
      27 | +    def run_test(self):
      28 | +        self.log.info("Add 2 block-relay-only connections to node 0")
    


    hebasto commented at 3:36 AM on March 22, 2021:

    nit: here and after s/"node 0"/"node"/ as it is the only node in this test.


    brunoerg commented at 10:37 PM on May 27, 2021:

    Perfect, thanks!

  53. in test/functional/feature_anchors.py:29 in 581791c620
      24 | +    def setup_network(self):
      25 | +        self.setup_nodes()
      26 | +
      27 | +    def run_test(self):
      28 | +        self.log.info("Add 2 block-relay-only connections to node 0")
      29 | +        for i in range(2):
    


    hebasto commented at 3:37 AM on March 22, 2021:

    nit: Numbers of connections, i.e., 2 and 5, could be named variables.

  54. in test/functional/feature_anchors.py:81 in 581791c620
      76 | +
      77 | +        self.log.info("Start node 0")
      78 | +        self.start_node(0)
      79 | +
      80 | +        self.log.info("When node starts, check if anchors.dat doesn't exist anymore")
      81 | +        assert not os.path.exists(node0_anchors_path)
    


    hebasto commented at 3:40 AM on March 22, 2021:

    The same assertion seems reasonable to place in the test beginning too, no?


    brunoerg commented at 10:00 PM on May 27, 2021:

    Yes, make sense.

  55. hebasto approved
  56. hebasto commented at 3:40 AM on March 22, 2021: member

    ACK 581791c62067403fbeb4e1fd88c1d80549627c94

  57. MarcoFalke merged this on Mar 24, 2021
  58. MarcoFalke closed this on Mar 24, 2021

  59. sidhujag referenced this in commit 07e9bfe193 on Mar 24, 2021
  60. MarcoFalke referenced this in commit 6985038046 on Jun 11, 2021
  61. sidhujag referenced this in commit e65843cadf on Jun 11, 2021
  62. PastaPastaPasta referenced this in commit e6cca13a10 on Jun 27, 2021
  63. PastaPastaPasta referenced this in commit e01c2baa72 on Jun 27, 2021
  64. PastaPastaPasta referenced this in commit 12301f9e94 on Jun 28, 2021
  65. PastaPastaPasta referenced this in commit 5d0e766e65 on Jun 28, 2021
  66. PastaPastaPasta referenced this in commit a199b449a2 on Jun 29, 2021
  67. PastaPastaPasta referenced this in commit c8f0ea9d17 on Jun 29, 2021
  68. PastaPastaPasta referenced this in commit 748115f23d on Jul 1, 2021
  69. PastaPastaPasta referenced this in commit a98ac0156d on Jul 1, 2021
  70. PastaPastaPasta referenced this in commit fc4cf8831a on Jul 1, 2021
  71. PastaPastaPasta referenced this in commit 1d83bd2d52 on Jul 1, 2021
  72. PastaPastaPasta referenced this in commit e02b6e3d38 on Jul 15, 2021
  73. Fabcien referenced this in commit 4073c6917f on Feb 2, 2022
  74. DrahtBot locked this on Aug 16, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-05-02 03:14 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me