lab.nexedi.com/kirr/go123@v0.0.0-20240207185015-8299741fa871/xnet/lonet/lonet_test.py (about)

     1  # -*- coding: utf-8 -*-
     2  # Copyright (C) 2018  Nexedi SA and Contributors.
     3  #                     Kirill Smelkov <kirr@nexedi.com>
     4  #
     5  # This program is free software: you can Use, Study, Modify and Redistribute
     6  # it under the terms of the GNU General Public License version 3, or (at your
     7  # option) any later version, as published by the Free Software Foundation.
     8  #
     9  # You can also Link and Combine this program with other software covered by
    10  # the terms of any of the Free Software licenses or any of the Open Source
    11  # Initiative approved licenses and Convey the resulting work. Corresponding
    12  # source of such a combination shall include the source code for all other
    13  # software used.
    14  #
    15  # This program is distributed WITHOUT ANY WARRANTY; without even the implied
    16  # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    17  #
    18  # See COPYING file for full licensing terms.
    19  # See https://www.nexedi.com/licensing for rationale and options.
    20  
    21  from golang import gimport, defer, func
    22  xerr  = gimport('lab.nexedi.com/kirr/go123/xerr')
    23  lonet = gimport('lab.nexedi.com/kirr/go123/xnet/lonet')
    24  
    25  from threading import Thread
    26  from cStringIO import StringIO
    27  import errno, logging as log
    28  
    29  
    30  def xread(sk):
    31      # XXX might get only part of sent data
    32      return sk.recv(4096)
    33  
    34  def xwrite(sk, data):
    35      sk.sendall(data)
    36  
    37  
    38  # TODO test that fd of listener can be used in select/epoll
    39  # TODO non-blocking mode
    40  
    41  
    42  # _test_virtnet_basic runs basic tests on a virtnet network implementation.
    43  # (this follows virtnettest.TestBasic)
    44  @func
    45  def _test_virtnet_basic(subnet):
    46      # (verifying that error log stays empty)
    47      errorlog  = StringIO()
    48      errorlogh = log.StreamHandler(errorlog)
    49      l = log.getLogger()
    50      l.addHandler(errorlogh)
    51      def _():
    52          l.removeHandler(errorlogh)
    53          assert errorlog.getvalue() == ""
    54      defer(_)
    55  
    56      defer(subnet.close)
    57  
    58      def xaddr(addr):
    59          return lonet.Addr.parse(subnet.network(), addr)
    60  
    61      ha = subnet.new_host("α")
    62      hb = subnet.new_host("β")
    63  
    64      assert ha.network() == subnet.network()
    65      assert hb.network() == subnet.network()
    66      assert ha.name() == "α"
    67      assert hb.name() == "β"
    68  
    69      try:
    70          ha.dial(":0")
    71      except Exception as e:
    72          assert xerr.cause(e) is lonet.ErrConnRefused
    73          assert str(e) == "dial %s α:1->α:0: [Errno %d] connection refused" % (subnet.network(), errno.ECONNREFUSED)
    74      else:
    75          assert 0, "connection not refused"
    76  
    77      l1 = ha.listen("")
    78      assert l1.addr() == xaddr("α:1")
    79  
    80      try:
    81          ha.dial(":0")
    82      except Exception as e:
    83          assert xerr.cause(e) is lonet.ErrConnRefused
    84          assert str(e) == "dial %s α:2->α:0: [Errno %d] connection refused" % (subnet.network(), errno.ECONNREFUSED)
    85      else:
    86          assert 0, "connection not refused"
    87  
    88  
    89      def Tsrv():
    90          c1s = l1.accept()
    91          assert c1s.local_addr()  == xaddr("α:2")
    92          assert c1s.getsockname() == ("α", 2)
    93          assert c1s.remote_addr() == xaddr("β:1")
    94          assert c1s.getpeername() == ("β", 1)
    95  
    96          assert xread(c1s) == "ping"
    97          xwrite(c1s, "pong")
    98  
    99          c2s = l1.accept()
   100          assert c2s.local_addr()  == xaddr("α:3")
   101          assert c2s.getsockname() == ("α", 3)
   102          assert c2s.remote_addr() == xaddr("β:2")
   103          assert c2s.getpeername() == ("β", 2)
   104  
   105          assert xread(c2s) == "hello"
   106          xwrite(c2s, "world")
   107  
   108  
   109      tsrv = Thread(target=Tsrv)
   110      tsrv.start()
   111  
   112      c1c = hb.dial("α:1")
   113      assert c1c.local_addr()  == xaddr("β:1")
   114      assert c1c.getsockname() == ("β", 1)
   115      assert c1c.remote_addr() == xaddr("α:2")
   116      assert c1c.getpeername() == ("α", 2)
   117  
   118      xwrite(c1c, "ping")
   119      assert xread(c1c) == "pong"
   120  
   121      c2c = hb.dial("α:1")
   122      assert c2c.local_addr()  == xaddr("β:2")
   123      assert c2c.getsockname() == ("β", 2)
   124      assert c2c.remote_addr() == xaddr("α:3")
   125      assert c2c.getpeername() == ("α", 3)
   126  
   127      xwrite(c2c, "hello")
   128      assert xread(c2c) == "world"
   129  
   130      tsrv.join()
   131  
   132      l2 = ha.listen(":0")
   133      assert l2.addr() == xaddr("α:4")
   134  
   135      subnet.close()
   136  
   137  
   138  def test_lonet_py_basic():
   139      subnet = lonet.join("")
   140      _test_virtnet_basic(subnet)
   141  
   142  
   143  # test interaction with lonet.go
   144  @func
   145  def test_lonet_py_go(network):
   146      subnet = lonet.join(network)
   147      defer(subnet.close)
   148  
   149      def xaddr(addr):
   150          return lonet.Addr.parse(subnet.network(), addr)
   151  
   152      hb = subnet.new_host("β")
   153      lb = hb.listen(":1")
   154  
   155      c1 = hb.dial("α:1")
   156      assert c1.local_addr() == xaddr("β:2")
   157      assert c1.remote_addr() == xaddr("α:2")
   158      assert xread(c1) == "hello py"
   159      xwrite(c1, "hello go")
   160      c1.close()
   161  
   162      c2 = lb.accept()
   163      assert c2.local_addr() == xaddr("β:2")
   164      assert c2.remote_addr() == xaddr("α:2")
   165      xwrite(c2, "hello2 go")
   166      assert xread(c2) == "hello2 py"
   167      c2.close()
   168  
   169  
   170  
   171  # go created a registry. verify we can read values from it and write something back too.
   172  # go side will check what we wrote.
   173  def test_registry_pygo(registry_dbpath):
   174      try:
   175          lonet.SQLiteRegistry(registry_dbpath, "ddd")
   176      except lonet.RegistryError as e:
   177          assert 'network name mismatch: want "ddd"; have "ccc"' in str(e)
   178      else:
   179          assert 0, 'network name mismatch not detected'
   180  
   181      r = lonet.SQLiteRegistry(registry_dbpath, "ccc")
   182      assert r.query("α") == "alpha:1234"
   183      assert r.query("β") is None
   184      r.announce("β", "beta:py")
   185      assert r.query("β") == "beta:py"
   186  
   187      try:
   188          r.announce("β", "beta:py2")
   189      except lonet.RegistryError as e:
   190          # XXX py escapes utf-8 with \
   191          #assert "announce ('β', 'beta:py2'): host already registered" in str(e)
   192          assert ": host already registered" in str(e)
   193      else:
   194          assert 0, 'duplicate host announce not detected'
   195  
   196      # ok - hand over checks back to go side.